package com.superbytecode.stencil.wrapper;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.superbytecode.stencil.entities.ConnectionObj;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * All rights Reserved, Designed By www.super-master.com
 *
 * @ProjectName: code-stencil
 * @Package: com.superbytecode.stencil.structure
 * @ClassName: DatasourceManager
 * @Description: [数据库管理工具]
 * <p> </p>
 * @Author: [Lance Ting]
 * @Date: 2024/10/12 14:57
 * @Version: V1.0
 * @Copyright: 2024 www.super-master.cn Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
@Slf4j
@UtilityClass
public class DatabaseManager {
    /*** 数据源 **/
    private final Map<String, DataSource> DATASOURCE = new ConcurrentHashMap<>(16);
    /*** 数据库连接对象 **/
    private final ThreadLocal<Connection> CONNECTION = new ThreadLocal<>();

    /**
     * 获取数据库连接对象
     *
     * @param connectionObj 参数
     * @return 连接对象
     */
    public Connection obtainConnection(ConnectionObj connectionObj) throws SQLException {
        // 数据库连接串设置
        if (Objects.isNull(CONNECTION.get())) {
            // 获取数据库链接资源对象
            DataSource dataSource = obtainDatasource(connectionObj);
            // 获取数据量连接对象
            Connection connection = dataSource.getConnection();
            CONNECTION.set(connection);
        }
        return CONNECTION.get();
    }

    /**
     * 获取数据库连接资源对象
     *
     * @param connectionObj 数据库连接配置
     * @return 数据库对象
     */
    public DataSource obtainDatasource(ConnectionObj connectionObj) {
        // 数据库连接串设置
        final String jdbcUrl = connectionObj.getJdbcUrl();
        DataSource dataSource = DATASOURCE.computeIfAbsent(jdbcUrl, key -> {
            try {
                Properties properties = prepareProperties();
                properties.put("url", jdbcUrl);
                properties.put("driverClassName", connectionObj.getDriverClass());
                properties.put("username", connectionObj.getUsername());
                properties.put("password", connectionObj.getPassword());
                // 创建数据库连接池对象
                return DruidDataSourceFactory.createDataSource(properties);
            } catch (Exception e) {
                log.error("obtain datasource error", e);
                return null;
            }
        });
        return Optional.ofNullable(dataSource).orElseThrow(() -> new IllegalArgumentException("create datasource failure!"));
    }

    /**
     * 预置数据库配置信息
     *
     * @return 配置信息
     */
    private Properties prepareProperties() {
        Properties properties = new Properties();
        // 初始连接数
        properties.put("initialSize", "1");
        // 最大活跃数
        properties.put("maxTotal", "30");
        properties.put("minIdle", "5");
        //properties.put("maxIdle", "10");
        // 最长等待时间(毫秒)
        properties.put("maxWaitMillis", "1000");
        // 程序中的连接不使用后是否被连接池回收
        properties.put("removeAbandonedOnMaintenance", true);
        properties.put("removeAbandonedOnBorrow", true);
        // 连接在所指定的秒数内未使用才会被删除(秒)
        properties.put("removeAbandonedTimeout", "5");
        return properties;
    }
}